package main

import (
	"github.com/gofiber/fiber"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"log"
)

type ProductType struct{
	Id int `gorm:"primary_key:id"`
	Name string
	//CreatedAt time.Time
	//UpdatedAt time.Time
}

type Product struct{
	Id int `gorm:"primary_key:id"`
	Name string
	Type ProductType `gorm:"ForeignKey:TypeId;AssociationForeignKey:Id"`
	TypeId int
	//CreatedAt time.Time
	//UpdatedAt time.Time
}

type ProjectType struct{
	Id int `gorm:"primary_key:id"`
	Name string
	//CreatedAt time.Time
	//UpdatedAt time.Time
}

type Project struct{
	Id int `gorm:"primary_key:id"`
	Name string
	Type ProjectType `gorm:"ForeignKey:TypeId;AssociationForeignKey:Id"`
	TypeId int
	//CreatedAt time.Time
	//UpdatedAt time.Time
}

type Meal struct{
	Id int `gorm:"primary_key:id"`
	Name string
	ProjectList []*Project `gorm:"many2many:meal_projects;"`
	ProductList []*Product `gorm:"many2many:meal_products;"`
	//CreatedAt time.Time
	//UpdatedAt time.Time
}

type Member struct{
	Id int `gorm:"primary_key:id"`
	Name string
	Meallist []*Meal `gorm:"many2many:member_meals;"`
	//CreatedAt time.Time
	//UpdatedAt time.Time
}

type ResponseData struct {
	Code int
	Data []*Member
	Message string
}

func main() {

	db, err := gorm.Open("mysql", "root:new_password@tcp(localhost:3306)/gorm_insert")
	if err != nil {
		panic("failed to connect database")
	}
	defer db.Close()

	db.AutoMigrate(&ProductType{}, &Product{}, &ProjectType{}, &Project{}, &Meal{}, &Member{})

	app := fiber.New()

	app.Post("/insertMember", func(c *fiber.Ctx) {

		//username := c.FormValue("username")
		//address := c.FormValue("address")

		var mb []*Member

		if err := c.BodyParser(&mb); err != nil {
			log.Fatal(err)
		}

		//if errj := json.Unmarshal([]byte(address), &mb); errj == nil{

		for _, jv := range mb{
			var m Member
			db.Where("id= ?", jv.Id).First(&m)
			if m.Id == 0{
				db.Create(jv)
			}
			for _, mv := range jv.Meallist{
				var ml Meal
				db.Where("id= ?", mv.Id).First(&ml)
				if ml.Id == 0{
					db.Create(mv)
				}
				db.Model(jv).Association("Meallist").Append(mv)

				for _, mvj := range mv.ProjectList{
					var jt ProjectType
					db.Where("id= ?", mvj.TypeId).First(&jt)
					if jt.Id == 0{
						db.Create(mvj.Type)
					}

					var j Project
					db.Where("id= ?", mvj.Id).First(&j)
					if j.Id == 0{
						db.Create(mvj)
					}
					db.Model(mv).Association("ProjectList").Append(mvj)

				}
				for _, mvd := range mv.ProductList{
					var dt ProductType
					db.Where("id= ?", mvd.TypeId).First(&dt)
					if dt.Id == 0{
						db.Create(mvd.Type)
					}
					var d Product
					db.Where("id= ?", mvd.Id).First(&d)
					if d.Id == 0{
						db.Create(mvd)
					}
					db.Model(mv).Association("ProductList").Append(mvd)
				}
			}
		}

		if err := c.JSON(fiber.Map{
			"code": 200,
			"message": "插入成功",
			"data": nil,
		}); err != nil {
			c.Status(500).Send(err)
			return
		}

		//} else {
		//	c.Status(500).Send(err)
		//	return
		//}
	})

	app.Post("/queryMember", func(c *fiber.Ctx) {

		var m []*Member
		db.Find(&m)
		for _, v := range m{
			db.Joins("JOIN member_meals ON member_meals.meal_id = meals.id AND member_meals.member_id = ?", v.Id).Find(&v.Meallist)

			for _, mv := range v.Meallist{
				db.Joins("JOIN meal_projects ON meal_projects.project_id = projects.id AND meal_projects.meal_id = ?", mv.Id).Find(&mv.ProjectList)

				for _, jv := range mv.ProjectList{
					db.Joins("JOIN projects ON project_types.id = projects.type_id AND projects.id = ?", jv.Id).Find(&jv.Type)
				}

				db.Joins("JOIN meal_products ON meal_products.product_id = products.id AND meal_products.meal_id = ?", mv.Id).Find(&mv.ProductList)

				for _, dv := range mv.ProductList{
					db.Joins("JOIN products ON product_types.id = products.type_id AND products.id = ?", dv.Id).Find(&dv.Type)

				}
			}
		}

		data := ResponseData{
			Code: 200,
			Data: m,
			Message: "成功",
		}

		if err := c.JSON(data); err != nil {
			c.Status(500).Send(err)
			return
		}

	})

	app.Listen(5390)
}


